package com.gk.panda.apis.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gk.panda.apis.Vo.BiologyFileVo;
import com.gk.panda.apis.dto.BiologyFileSaveDto;
import com.gk.panda.apis.dto.BiologyFileSearchDto;
import com.gk.panda.apis.dto.BiologyPointSaveDto;
import com.gk.panda.apis.mapper.BiologyFileMapper;
import com.gk.panda.apis.service.*;
import com.gk.panda.commons.exception.ServerException;
import com.gk.panda.commons.util.UserUtil;
import com.gk.panda.pojo.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class BiologyFileServiceImpl extends ServiceImpl<BiologyFileMapper, BiologyFile> implements BiologyFileService {

    @Autowired
    private UserService userService;

    @Autowired
    private RoleService roleService;

    @Autowired
    private RealtimeShootService realtimeShootService;

    @Autowired
    private FdfsService fdfsService;

    @Autowired
    private BiologyPointService biologyPointService;

    @Autowired
    private BiodiversityService biodiversityService;

    /**
     * 分页查询生物附件
     *
     * @param dto
     * @return
     */
    @Override
    public Page<BiologyFileVo> listBiologyFile(BiologyFileSearchDto dto) {
        QueryWrapper<BiologyFile> wrapper = new QueryWrapper<>();
        wrapper.eq("biology_kingdom", dto.getBiologyKingdom());
        wrapper.eq("type", dto.getType());
//        wrapper.like(StringUtils.isNotEmpty(dto.getBiologyName()), "biology_name", dto.getBiologyName());
        if (StringUtils.isNotEmpty(dto.getBiologyName())) {
            wrapper.and(queryWrapper -> {
                queryWrapper.like("biology_name", dto.getBiologyName())
                        .or().like("device_code", dto.getBiologyName());
            });
        }
        wrapper.in(dto.getOrgIds() != null, "org_id", dto.getOrgIds());
        wrapper.ge(dto.getStartTime() != null, "shooting_time", dto.getStartTime());
        wrapper.le(dto.getEndTime() != null, "shooting_time", dto.getEndTime());
        wrapper.orderByDesc("shooting_time");
        List<BiologyFile> biologyFiles = list(wrapper);
        Map<String, List<BiologyFile>> map = biologyFiles.stream().collect(Collectors.groupingBy(BiologyFile::getBiologyName));
        List<BiologyFileVo> vos = map.entrySet().stream().map(e -> new BiologyFileVo(e.getKey(), e.getValue())).collect(Collectors.toList());
        Collections.sort(vos, new Comparator<BiologyFileVo>() {
            @Override
            public int compare(BiologyFileVo o1, BiologyFileVo o2) {
                long num = o1.getBiologyFiles().get(0).getShootingTime().getTime() - o2.getBiologyFiles().get(0).getShootingTime().getTime();
                if (num > 0) {
                    return -1;
                } else if (num < 0) {
                    return 1;
                } else {
                    return o1.getBiologyName().hashCode() - o2.getBiologyName().hashCode();
                }
            }
        });
        //当前页
        int current = dto.getPageNumber();
        //每页数据条数
        int size = dto.getPageSize();
        Page<BiologyFileVo> page = new Page<>(current, size);
        int count = vos.size();
        List<BiologyFileVo> pageList = new ArrayList<>();
        //计算当前页第一条数据的下标
        int currId = current > 1 ? (current - 1) * size : 0;
        for (int i = 0; i < size && i < count - currId; i++) {
            pageList.add(vos.get(currId + i));
        }
        page.setSize(size);
        page.setCurrent(current);
        page.setTotal(count);
        //计算分页总页数
        page.setPages(count % 10 == 0 ? count / 10 : count / 10 + 1);
        page.setRecords(pageList);
        return page;
    }

    /**
     * 添加生物附件
     *
     * @param dto
     * @return
     */
    @Override
    public boolean addBiologyFile(BiologyFileSaveDto dto) {
        if (dto.getShootingTime() == null) {
            dto.setShootingTime(new Date());
        }
        String username = UserUtil.getCurrentUser();
        int orgId = UserUtil.getCurrentUserOrgId();
        String[] urls = dto.getUrl().split(",");
        List<BiologyFile> biologyFiles = new ArrayList<>();
        for (String url : urls) {
            BiologyFile biologyFile = new BiologyFile();
            BeanUtils.copyProperties(dto, biologyFile);
            biologyFile.setUrl(url);
            biologyFile.setCreator(username);
            biologyFile.setOrgId(orgId);
            biologyFiles.add(biologyFile);
        }
        //如果是图片资源，则增加GIS打点
        if (dto.getType() == 0) {
            String lot = dto.getLot();//经度
            String lat = dto.getLat();//纬度
            //经纬度不为null时打点
            if (StringUtils.isNotEmpty(lot) && StringUtils.isNotEmpty(lat)) {
                //查看此物种GIS点位
                BiologyPoint biologyPoint = biologyPointService.getOne(Wrappers.<BiologyPoint>lambdaQuery().eq(BiologyPoint::getName, dto.getBiologyName()));
                //如果有此物种点位，则在原有基础上打点
                if (biologyPoint != null) {
                    String point = "[" + lot +"," + lat + "]";
                    String geoJson = biologyPoint.getGeoJson();//原geoJson
                    if (!geoJson.contains(point)) {
                        String[] split = geoJson.split("]}");
                        geoJson = split[0] + "," + point + "]}" + split[1];
                        biologyPointService.update(Wrappers.<BiologyPoint>lambdaUpdate().eq(BiologyPoint::getId,biologyPoint.getId())
                                .set(BiologyPoint::getGeoJson,geoJson));
                    }
                } else {//没有此物种点位则新建一个
                    Biodiversity biodiversity = biodiversityService.getOne(Wrappers.<Biodiversity>lambdaQuery().eq(Biodiversity::getSpecies, dto.getBiologyName()));
                    BiologyPointSaveDto saveDto = new BiologyPointSaveDto();
                    saveDto.setProtectionLevel(biodiversity.getProtectionLevel());
                    saveDto.setPicUrl(urls[0]);
                    saveDto.setName(biodiversity.getSpecies());
                    saveDto.setKingdom(biodiversity.getKingdom());
                    saveDto.setBioId(biodiversity.getId());
                    String[] strs = {lot, lat};
                    List<String[]> place = new ArrayList<>();
                    place.add(strs);
                    saveDto.setPlace(place);
                    biologyPointService.addBiologyPoint(saveDto);
                }
            }
        }
        return saveBatch(biologyFiles);
    }

    /**
     * 删除生物附件
     *
     * @param id
     * @return
     */
    @Override
    public int deleteBiologyFile(String id) {
        String[] ids = id.split(",");
        List<BiologyFile> biologyFiles = listByIds(Arrays.asList(ids));
        String username = UserUtil.getCurrentUser();
        User user = userService.getById(username);
        Integer roleId = user.getRoleId();
        Role role = roleService.getById(roleId);
        //如果是普通管理员并且不是本人创建的不能删除
        if (role.getType() == 3) {
            if (!username.equals(biologyFiles.get(0).getCreator())) return -1;
//            int i = baseMapper.deleteBatchIds(Arrays.asList(ids));
//            if (i == ids.length) return 1;
//            return 0;
        } else {
            List<Integer> orgIds = userService.getOperableOrg(username);
            Integer orgId = biologyFiles.get(0).getOrgId();
            if (!orgIds.contains(orgId)) return -1;
        }
        baseMapper.deleteBatchIds(Arrays.asList(ids));
        //归档的图片视频删除时将关联的实时抓拍回退为未归档状态
        List<RealtimeShoot> realtimeShoots = realtimeShootService.list(Wrappers.<RealtimeShoot>lambdaQuery().in(RealtimeShoot::getFileRelation, Arrays.asList(ids)));
        if (CollectionUtils.isNotEmpty(realtimeShoots)) {
            //归档的图片视频删除时不能删除源文件
            List<String> list = realtimeShoots.stream().map(RealtimeShoot::getFileRelation).collect(Collectors.toList());
            biologyFiles.forEach(biologyFile -> {
                if (!list.contains(biologyFile.getId().toString())) {
                    fdfsService.deleteFile(biologyFile.getUrl());
                }
            });
            //实时抓拍回退归档状态
            realtimeShoots.forEach(realtimeShoot -> realtimeShootService.update(Wrappers.<RealtimeShoot>lambdaUpdate().eq(RealtimeShoot::getId, realtimeShoot.getId())
                    .set(RealtimeShoot::getFileStatus, 0).set(RealtimeShoot::getFileRelation, null).set(RealtimeShoot::getFileType, null)));
        }
        return 1;
    }

    /**
     * 根据附件id将附件设置为卡片封面
     *
     * @param id
     * @return
     */
    @Override
    public boolean setCover(int id) {
        BiologyFile biologyFile = getById(id);
        biologyFile.setIsCover(0);
        updateById(biologyFile);
        UpdateWrapper<BiologyFile> wrapper = new UpdateWrapper<>();
        wrapper.set("is_cover", 1).eq("biology_name", biologyFile.getBiologyName())
                .eq("is_cover", 0);
        update(wrapper);
        return true;
    }

    /**
     * 批量上传生物附件
     *
     * @param files
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String uploadBatch(Integer kingdom, String biologyName, MultipartFile[] files) {
        if (files != null && files.length > 0) {
            List<String> imageExtension = Arrays.asList("jpeg", "jpg", "bmp", "png");
            List<String> videoExtension = Arrays.asList("avi", "mp4", "wmv", "rmvb");
            List<BiologyFile> biologyFiles = new ArrayList<>();
            List<String> urls = new ArrayList<>();
            try {
                SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmm");
                String time = format.format(new Date());
                for (MultipartFile file : files) {

                    //获取文件上传的名称
                    String originalFilename = file.getOriginalFilename();
                    if (StringUtils.isBlank(originalFilename)) {
                        throw new ServerException("上传文件有误，请确认！");
                    }

                    String[] fileNameAttr = originalFilename.split("\\.");
                    //获取文件的后缀
                    String suffix = fileNameAttr[fileNameAttr.length - 1];
                    BiologyFile biologyFile = new BiologyFile();
//                String endWith = url.substring(url.lastIndexOf(".") + 1);
                    if (imageExtension.contains(suffix.toLowerCase())) {
                        biologyFile.setType(0);
                    } else if (videoExtension.contains(suffix.toLowerCase())) {
                        biologyFile.setType(1);
                    } else continue;
                    String url = fdfsService.uploadFile(file, suffix);
                    urls.add(url);
                    biologyFile.setUrl(url);
                    biologyFile.setBiologyKingdom(kingdom);
                    biologyFile.setOrgId(UserUtil.getCurrentUserOrgId());
//                    biologyFile.setBiologyName(null != biologyName ? biologyName : "待修改" + UUID.randomUUID().toString().replace("-", ""));
                    biologyFile.setBiologyName(null != biologyName ? biologyName : time);
                    biologyFiles.add(biologyFile);
                }
            } catch (Exception e) {
                urls.forEach(url -> fdfsService.deleteFile(url));
            }
            saveBatch(biologyFiles);
            return "上传成功";
        }
        return "文件不能为空";
    }
}
